##########################################
## Copyright 2012-2013 Ceruti Francesco & contributors
##
## This file is part of LiSP (Linux Show Player).
##########################################

from PyQt4 import QtCore, QtGui


def timestr(seconds):
    return "%02d:%02d" % divmod(seconds, 60)


class QTimeLineView(QtGui.QAbstractScrollArea):

    def __init__(self, pixelSecond, parent=None):
        super(QTimeLineView, self).__init__(parent)

        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.horizontalScrollBar().setPageStep(1)
        self.horizontalScrollBar().setSingleStep(1)
        self.horizontalScrollBar().valueChanged.connect(self.onScroll)

        self._wave = None
        self._mMask = QMarkersArea(pixelSecond, self.viewport())
        self._time = QTimeLineWidget(pixelSecond, self.viewport())

        self._pixelSecond = pixelSecond

    def setWaveform(self, peaks, rms, antialising=False):
        self._wave = QWaveformWidget(peaks, rms, antialising)
        self._wave.setParent(self.viewport())

        self._mMask.raise_()

    def resizeEvent(self, e):
        self._time.setGeometry(0, 0, self.width() - 1, 20)

        if(self._wave is not None):
            self._wave.setGeometry(0, 20, self.width() - 1, self.height() - 20)
            self._mMask.setGeometry(self._wave.geometry())

            self.horizontalScrollBar().setMaximum(int((len(self._wave) - self.width()) / self._pixelSecond) + 1)

    def onScroll(self, value):
        value *= self._pixelSecond
        self._wave.scrollTo(value)
        self._time.scrollTo(value)
        self._mMask.scrollTo(value)

    '''def mousePressEvent(self, event):
        time = (event.x() + self.horizontalScrollBar().value() * self._pixelSecond) / self._pixelSecond

        print(timestr(time))

        time = int(time * 10) / 10

        if(event.button() == QtCore.Qt.LeftButton):
            self._mMask.addTimeMarker(time)
        else:
            self._mMask.addAreaMarker(time, 1)'''


class QTimeMarker(QtGui.QWidget):

    def __init__(self, time, parent=None):
        super(QTimeMarker, self).__init__(parent)

        self.time = time

        self.show()

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.fillRect(0, 0, 3, self.height(), QtGui.QColor(255, 0, 0, 150))

    def mousePressEvent(self, event):
        event.accept()


class QAreaMarker(QtGui.QWidget):

    def __init__(self, time, duration, parent=None):
        super(QAreaMarker, self).__init__(parent)

        self.time = time
        self.duration = duration

        self.show()

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.fillRect(self.rect(), QtGui.QColor(255, 0, 0, 100))

    def mousePressEvent(self, event):
        event.accept()


class QMarkersArea(QtGui.QWidget):

    def __init__(self, pixelSecond, parent=None):
        super(QMarkersArea, self).__init__(parent)

        self._time_marker = []
        self._area_marker = []

        self._pixelSecond = pixelSecond
        self._startPixel = 0

    def addTimeMarker(self, time):
        marker = QTimeMarker(time, self)
        marker.setGeometry(time * self._pixelSecond, 0, round(self._pixelSecond / 10), self.height())
        self._time_marker.append(marker)

        self.update()

    def addAreaMarker(self, time, duration):
        marker = QAreaMarker(time, duration, self)
        marker.setGeometry(time * self._pixelSecond, 0, duration * self._pixelSecond, self.height())
        self._area_marker.append(marker)

        self.update()

    def scrollTo(self, value):
        self._startPixel = value
        self.update()

    def update(self):
        super().update()
        self.setGeometry(-self._startPixel, self.y(), self.width() + self._startPixel, self.height())


class QTimeLineWidget(QtGui.QWidget):

    def __init__(self, pixelSecond, parent=None):
        super(QTimeLineWidget, self).__init__(parent)

        self._pixelSecond = pixelSecond
        self._startPixel = 0

    def scrollTo(self, value):
        self._startPixel = value
        self.repaint()

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)

        grad = QtGui.QLinearGradient()
        grad.setColorAt(0, QtGui.QColor(30, 30, 30))
        grad.setColorAt(0.7, QtGui.QColor(80, 80, 80))
        grad.setColorAt(1, QtGui.QColor(100, 100, 100))
        grad.setStart(0, 0)
        grad.setFinalStop(0, self.rect().height())

        painter.fillRect(self.rect(), grad)
        painter.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255)))

        font = painter.font()
        font.setPixelSize(11)
        painter.setFont(font)

        for i in range(int(self.width() / self._pixelSecond) + 1):
            x = i * self._pixelSecond
            painter.drawLine(x, 0, x, self.rect().height() - 2)
            painter.drawText(x + 5, self.rect().height() / 2 + 5, timestr(i + self._startPixel / self._pixelSecond))

        painter.end()


class QWaveformWidget(QtGui.QWidget):

    def __init__(self, peaks=[], rms=[], antialiasing=False, parent=None):
        super(QWaveformWidget, self).__init__(parent)

        self.peakColor = QtGui.QColor(30, 220, 110)  # QtGui.QColor(0, 0, 100)
        self.rmsColor = QtGui.QColor(100, 255, 180)  # QtGui.QColor(0, 0, 200)

        self.antialiasing = antialiasing

        self._peaks = peaks
        self._rms = rms

        self._startPixel = 0

    def scrollTo(self, value):
        self._startPixel = value
        self.repaint()

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)

        if(self.antialiasing):
            painter.setRenderHints(QtGui.QPainter.Antialiasing)

        painter.translate(-self._startPixel, self.rect().height() / 2)

        if(len(self._peaks) > 0):
            painter.setPen(QtGui.QPen(self.peakColor))
            painter.drawLines(self._peaks[self._startPixel:self.width() + self._startPixel])

        if(len(self._rms) > 0):
            painter.setPen(QtGui.QPen(self.rmsColor))
            painter.drawLines(self._rms[self._startPixel:self.width() + self._startPixel])

        painter.end()

    def __len__(self):
        return max(len(self._peaks), len(self._rms))
